/**
 *  VirtualStack.java : IceBird project
 *  19:25:40 
 */
package icebird.compiler.ncomp.vs;


import icebird.compiler.ncomp.X86Register;
import icebird.metadata.BasicType;


/**
 * @author Sergey Shulepoff[Knott]
 */
public final class VirtualStack {

	private Item[] stack;
	private int peek;
	
	private FPUStack fpu = new FPUStack();
	
	public VirtualStack() {
		reset();
	}
	
	/**
	 * Reset stack.
	 * @return void
	 */
	public void reset() {
		stack = new Item[8];
		peek = 0;
	}
	
	/**
	 * Gets element count.
	 * @return int
	 */
	public int getSize() {
		return peek;
	}
	
	/**
	 * Grow.
	 * @return void
	 */
	private void grow() {
		Item[] tmp = new Item[stack.length];
		System.arraycopy(stack, 0, tmp, 0, stack.length);
		
		stack = tmp;
	}
	
	/**
	 * Pop.
	 * @return Item
	 */
	public Item pop() {
		return stack[--peek];
	}
	
	/**
	 * Pop.
	 * @return Item
	 */
	public Item pop(BasicType type) {
		Item i = pop();
		
		if (i.getType() != type) {
			throw new IllegalStateException();
		}
		
		return i;
	}
	
	public IntegerItem popInteger() {
		return (IntegerItem)pop(BasicType.Int);
	}
	
	/**
	 * Push value.
	 * @return void
	 */
	public void push(Item i) {
		if (stack.length == peek) {
			grow();
		}
		
		stack[peek++] = i;
	}
	
	/**
	 * Push value.
	 * @return void
	 */
	public void push() {
		int i = 0;
		
		while (i < peek) {
			Item item = stack[i++];
			item.push();
		}
	}
	
	public void loadLocal(int offset) {
		for (int i = 0; i < peek; i++) {
			Item item = stack[i];
			
			if (item.getLocation().isLocal()) {
				if (((LocalLocation)item.getLocation()).getOffset() == offset) 
					item.load();
			}
		}
	}
	
	/**
	 * Is this stack uses.
	 * @return boolean
	 */
	public boolean uses(X86Register r) {
		for (Item i : stack) {
			if (i.uses(r)) return true;
		}
		
		return false;
	}

	/**
	 * Gets fpu stack.
	 * @return FPUStack
	 */
	public FPUStack getFPUStack() {
		return fpu;
	}

	public WordItem popWord() {
		return (WordItem)pop();
	}
	
	public boolean isEmpty() {
		return getSize() == 0;
	}
}
